﻿#include <iostream>
#include <boost/asio.hpp>
#include <set>
#include <memory>

using boost::asio::ip::tcp;
using namespace std;

const int MAX_LENTH = 1024;
typedef shared_ptr<tcp::socket> socket_ptr;
set<shared_ptr<thread>> thread_set;

// 服务器处理客户端的读和写
void session(socket_ptr sock)
{
	try
	{
		for (;;)
		{
			char data[MAX_LENTH];
			memset(data, '\0', MAX_LENTH);
			boost::system::error_code error;
			// 直到读到最长为止，要读到1024字节
			//size_t length = boost::asio::read(sock, boost::asio::buffer(data, MAX_LENTH), error);
			// 部分读取，读多少算多少
			size_t length = sock->read_some(boost::asio::buffer(data, MAX_LENTH), error);
			if (error == boost::asio::error::eof)
			{
				cout << "connection closed" << endl;
				break;
			}
			else if (error)
			{
				throw boost::system::system_error(error);
			}
			cout << "receive from " << sock->remote_endpoint().address().to_string() << endl;
			cout << "receive message is " << data << endl;
			// 将数据传递回去
			boost::asio::write(*sock, boost::asio::buffer(data, MAX_LENTH));
		}
	}
	catch (exception& e)
	{
		cerr << "Exception in thread" << e.what() << endl;
	}
}

void server(boost::asio::io_context& ioc, unsigned short port)
{
	// 专门来接受连接，必须按照传递方式，Acceptor是归属于某个ioc，以及用ipv4的方式进行绑定到端口
	tcp::acceptor a(ioc, tcp::endpoint(tcp::v4(), port));
	for (;;)
	{
		socket_ptr socket(new tcp::socket(ioc));
		a.accept(*socket);
		// 创建线程，做session工作，参数是Socket，等待客户端发数据，回传等工作
		auto t = make_shared<thread>(session, socket);
		thread_set.insert(t);
	}
}

int main()
{
	try
	{
		boost::asio::io_context ioc;
		server(ioc, 10086);
		for (auto& t : thread_set)
		{
			t->join();
		}
	}
	catch (exception& e)
	{
		cerr << "Exception in thread" << e.what() << endl;
	}
	return 0;
}